package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.mapper.CourseTeacherMapper;
import com.xuecheng.content.mapper.TeachplanMapper;
import com.xuecheng.content.mapper.TeachplanMediaMapper;
import com.xuecheng.content.model.dto.SaveTeachplanDto;
import com.xuecheng.content.model.dto.TeachplanDto;
import com.xuecheng.content.model.po.CourseBase;
import com.xuecheng.content.model.po.CourseTeacher;
import com.xuecheng.content.model.po.Teachplan;
import com.xuecheng.content.model.po.TeachplanMedia;
import com.xuecheng.content.service.TeachplanService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {
    @Autowired
    TeachplanMapper teachplanMapper;

    @Autowired
    TeachplanMediaMapper teachplanMediaMapper;

    @Autowired
    CourseTeacherMapper courseTeacherMapper;

    @Autowired
    CourseBaseMapper courseBaseMapper;

    @Override
    public List<TeachplanDto> selectTreeNodes(Long courseId) {
        return teachplanMapper.selectTreeNodes(courseId);
    }

    @Override
    @Transactional
    public void saveTeachplan(SaveTeachplanDto teachplan) {
        //判断操作是新增还是修改
        Long courseId = teachplan.getCourseId();
        Long parentid = teachplan.getParentid();

        Long id = teachplan.getId();

        if (id == null) {
            //查不到则为新增
            Teachplan teachplan1 = new Teachplan();
            //查询新增节点级别所有的课程数量
            Integer count = lambdaQuery()
                    .eq(Teachplan::getCourseId, courseId)
                    .eq(Teachplan::getParentid, parentid)
                    .count();
            BeanUtils.copyProperties(teachplan, teachplan1);
            teachplan1.setOrderby(count + 1);
            this.save(teachplan1);

        } else {
            //修改
            Teachplan teachplan2 = new Teachplan();
            BeanUtils.copyProperties(teachplan, teachplan2);
            this.updateById(teachplan2);
        }
    }

    @Override
    @Transactional
    public void deleteTeachplan(Long id) {
        //查询数据库 判断该条课程计划是否属于大章节 以parentId为判断依据
        Teachplan teachplan = this.getById(id);
        Long parentid = teachplan.getParentid();
        if (parentid != 0) {
            // 该课程计划为小章节 直接删除小章节 并将关联的Teachplan_media表内信息删除
            this.removeById(id);
            //删除关联表内的信息
            LambdaQueryWrapper<TeachplanMedia> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TeachplanMedia::getTeachplanId, id);
            teachplanMediaMapper.delete(wrapper);
            return;
        }
        //如果是大章节,则先判断旗下是否有小章节
        List<Teachplan> teachplanList = lambdaQuery().eq(Teachplan::getParentid, id).list();
        if (teachplanList.isEmpty() | teachplanList == null) {
            //该大章节下没有小章节,可以直接删除
            this.removeById(id);
            return;
        }

        //如果大章节下有小章节,则返回删除失败的提示信息
        throw new XueChengPlusException("课程计划信息还有子级信息,无法操作");
    }

    @Override
    @Transactional
    public void movedownTeachplan(Long id) {
        //先查询该课程计划
        Teachplan teachplan = this.getById(id);
        //获取课程id 父节点 id 以及排序字段orderby
        Long parentid = teachplan.getParentid();
        Long courseId = teachplan.getCourseId();
        Integer orderby = teachplan.getOrderby();
        //根据课程id 和 父节点id查询该大章节下的所有子节点数据目录
        List<Teachplan> teachplanList = lambdaQuery()
                .eq(Teachplan::getParentid, parentid)
                .eq(Teachplan::getCourseId, courseId)
                .list();
        //通过stream流获取子节点的排序字段值,存入一个集合内
        List<Integer> orderList = new ArrayList<>();
        teachplanList.stream().forEach(item -> {
            orderList.add(item.getOrderby());
        });
        //将子节点对象 存储为:排序字段为键的 对象本身为值的 map集合
        Map<Integer, Teachplan> teachplanMap = teachplanList
                .stream().collect(Collectors.toMap(key -> key.getOrderby(), value -> value));

        //对orderList集合进行排序(默认升序)
        Collections.sort(orderList);
        //根据元素获得集合内元素所在的索引
        int index = orderList.indexOf(orderby);
        //获取排序子弹集合的集合大小
        int size = orderList.size();
        if (index + 1 == size) {
            //表示该排序字段在集合内的最后位置,无法再进行向下移动 直接返回
            return;
        }

        //获取该字段的下一个元素(即 向下移动所在位置元素的排序字段值)
        Integer newOrderby = orderList.get(index + 1);
        Teachplan NewTeachplan = teachplanMap.get(newOrderby);
        //交换两者的排序字段
        NewTeachplan.setOrderby(orderby);
        teachplan.setOrderby(newOrderby);
        //更新课程计划
        this.updateById(NewTeachplan);
        this.updateById(teachplan);
    }

    @Override
    @Transactional
    public void moveupTeachplan(Long id) {
        //先查询该课程计划
        Teachplan teachplan = this.getById(id);
        //获取课程id 父节点 id 以及排序字段orderby
        Long parentid = teachplan.getParentid();
        Long courseId = teachplan.getCourseId();
        Integer orderby = teachplan.getOrderby();
        //根据课程id 和 父节点id查询该大章节下的所有子节点数据目录
        List<Teachplan> teachplanList = lambdaQuery()
                .eq(Teachplan::getParentid, parentid)
                .eq(Teachplan::getCourseId, courseId)
                .list();
        //通过stream流获取子节点的排序字段值,存入一个集合内
        List<Integer> orderList = new ArrayList<>();
        teachplanList.stream().forEach(item -> {
            orderList.add(item.getOrderby());
        });
        //将子节点对象 存储为:排序字段为键的 对象本身为值的 map集合
        Map<Integer, Teachplan> teachplanMap = teachplanList
                .stream().collect(Collectors.toMap(key -> key.getOrderby(), value -> value));

        //对orderList集合进行排序(默认升序)
        Collections.sort(orderList);
        //根据元素获得集合内元素所在的索引
        int index = orderList.indexOf(orderby);
        //获取排序子弹集合的集合大小
        int size = orderList.size();
        if (index == 0) {
            //表示该排序字段在集合内的第一个位置,无法再进行向上移动 直接返回
            return;
        }

        //获取该字段的上一个元素(即 向上移动所在位置元素的排序字段值)
        Integer newOrderby = orderList.get(index - 1);
        Teachplan NewTeachplan = teachplanMap.get(newOrderby);
        //交换两者的排序字段
        NewTeachplan.setOrderby(orderby);
        teachplan.setOrderby(newOrderby);
        //更新课程计划
        this.updateById(NewTeachplan);
        this.updateById(teachplan);
    }

    @Override
    @Transactional
    public List<CourseTeacher> getCourseTeacher(Long courseId) {
        LambdaQueryWrapper<CourseTeacher> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseTeacher::getCourseId, courseId);
        List<CourseTeacher> courseTeacherList = courseTeacherMapper.selectList(wrapper);
        return courseTeacherList;
    }

    @Override
    @Transactional
    public CourseTeacher addCourseTeacher(CourseTeacher courseTeacher, Long companyId) {
        Long courseId = courseTeacher.getCourseId();
        CourseBase courseBase = courseBaseMapper.selectById(courseId);

        if (!courseBase.getCompanyId().equals(companyId)) {
            throw new XueChengPlusException("只能向本机构自己的课程内添加老师");
        }

        Long id = courseTeacher.getId();

        if(id == null){
            //添加老师
            int i = courseTeacherMapper.insert(courseTeacher);

            if (i < 1) {
                throw new XueChengPlusException("添加老师失败");
            }

            return courseTeacherMapper.selectById(courseTeacher.getId());
        }

        //如果参数id有值,则为修改对象
        int i = courseTeacherMapper.updateById(courseTeacher);

        if (i < 1) {
            throw new XueChengPlusException("修改老师失败");
        }

        return courseTeacherMapper.selectById(courseTeacher.getId());
    }

    @Override
    @Transactional
    public void deleteCourseTeacher(Long courseId, Long id, Long companyId) {
        CourseBase courseBase = courseBaseMapper.selectById(courseId);
        if (!courseBase.getCompanyId().equals(companyId)) {
            throw new XueChengPlusException("只能向本机构自己的课程内删除老师");
        }
        courseTeacherMapper.deleteById(id);
    }
}
